//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

namespace OpenLS.Spreadsheet.UI
{
    class SelectionAndActiveControl: FrameworkElement
    {



        public Range Selection
        {
            get { return (Range)GetValue(SelectionProperty); }
            set { SetValue(SelectionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Selection.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectionProperty =
            DependencyProperty.Register("Selection", typeof(Range), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender));



        public RowCollection Rows
        {
            get { return (RowCollection)GetValue(RowsProperty); }
            set { SetValue(RowsProperty, value); }
        }


        // Using a DependencyProperty as the backing store for Rows.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RowsProperty =
            DependencyProperty.Register("Rows", typeof(RowCollection), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange, OnRowsChanged));

        static void OnRowsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var This = (SelectionAndActiveControl)d;
            var rows = (RowCollection)e.NewValue;
            if (rows != null)
                rows.LayoutChanged += This.OnLayoutChanged;
        }
        public ColumnCollection Columns
        {
            get { return (ColumnCollection)GetValue(ColumnsProperty); }
            set { SetValue(ColumnsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Columns.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColumnsProperty =
            DependencyProperty.Register("Columns", typeof(ColumnCollection), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsArrange, OnColumnsChanged));
        static void OnColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var This = (SelectionAndActiveControl)d;
            var columns = (ColumnCollection)e.NewValue;
            if (columns != null)
                columns.LayoutChanged += This.OnLayoutChanged;
        }

        void OnLayoutChanged(object sender, EventArgs args)
        {
            InvalidateVisual();
        }


        public int ActiveRow
        {
            get { return (int)GetValue(ActiveRowProperty); }
            set { SetValue(ActiveRowProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ActiveRow.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ActiveRowProperty =
            DependencyProperty.Register("ActiveRow", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));


        public int ActiveColumn
        {
            get { return (int)GetValue(ActiveColumnProperty); }
            set { SetValue(ActiveColumnProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ActiveRow.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ActiveColumnProperty =
            DependencyProperty.Register("ActiveColumn", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));




        public int ActiveRowSpan
        {
            get { return (int)GetValue(ActiveRowSpanProperty); }
            set { SetValue(ActiveRowSpanProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ActiveRowSpan.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ActiveRowSpanProperty =
            DependencyProperty.Register("ActiveRowSpan", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsRender));




        public int ActiveColumnSpan
        {
            get { return (int)GetValue(ActiveColumnSpanProperty); }
            set { SetValue(ActiveColumnSpanProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ActiveColumnSpan.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ActiveColumnSpanProperty =
            DependencyProperty.Register("ActiveColumnSpan", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsRender));



        public int SelectionRow
        {
            get { return (int)GetValue(SelectionRowProperty); }
            set { SetValue(SelectionRowProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectionRow.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectionRowProperty =
            DependencyProperty.Register("SelectionRow", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));



        public int SelectionColumn
        {
            get { return (int)GetValue(SelectionColumnProperty); }
            set { SetValue(SelectionColumnProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectionColumn.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectionColumnProperty =
            DependencyProperty.Register("SelectionColumn", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));



        public int SelectionColumnSpan
        {
            get { return (int)GetValue(SelectionColumnSpanProperty); }
            set { SetValue(SelectionColumnSpanProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectionColumnSpan.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectionColumnSpanProperty =
            DependencyProperty.Register("SelectionColumnSpan", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsRender));



        public int SelectionRowSpan
        {
            get { return (int)GetValue(SelectionRowSpanProperty); }
            set { SetValue(SelectionRowSpanProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectionRowSpan.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectionRowSpanProperty =
            DependencyProperty.Register("SelectionRowSpan", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsRender));



        public bool IsSelectionFullRow
        {
            get { return (bool)GetValue(IsSelectionFullRowProperty); }
            set { SetValue(IsSelectionFullRowProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsSelectionFullRow.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsSelectionFullRowProperty =
            DependencyProperty.Register("IsSelectionFullRow", typeof(bool), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));



        public bool IsSelectionFullColumn
        {
            get { return (bool)GetValue(IsSelectionFullColumnProperty); }
            set { SetValue(IsSelectionFullColumnProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsSelectionFullColumn.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsSelectionFullColumnProperty =
            DependencyProperty.Register("IsSelectionFullColumn", typeof(bool), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));



        public int Top
        {
            get { return (int)GetValue(TopProperty); }
            set { SetValue(TopProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Top.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TopProperty =
            DependencyProperty.Register("Top", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));




        public int Left
        {
            get { return (int)GetValue(LeftProperty); }
            set { SetValue(LeftProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Left.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LeftProperty =
            DependencyProperty.Register("Left", typeof(int), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));


        
        private WorksheetGrid.LayoutInfo layoutInfo;
        protected Rect GetRect(CellAddress address, int colSpan, int rowSpan)
        {
            Rect r = layoutInfo.GetRect(address, new CellSpan(rowSpan, colSpan));
            return r;
        }
        protected override void OnRender(DrawingContext drawingContext)
        {
            if (Columns == null || Rows == null || Selection == null)
                return;
            if (layoutInfo == null)
            layoutInfo = new WorksheetGrid.LayoutInfo(new CellPosition{Column = Left, Row=Top}, Columns, Rows, new Size(ActualWidth, ActualHeight));
            Rect activeRect = GetRect(new CellAddress(ActiveRow, ActiveColumn), ActiveColumnSpan, ActiveRowSpan);
            Geometry selectionGeometry = null;
            foreach (var range in GetSimpleRanges(Selection))
            {
                if (selectionGeometry == null)
                    selectionGeometry = GetRangeReometry(range);
                else
                    selectionGeometry = new CombinedGeometry(GeometryCombineMode.Union, selectionGeometry, GetRangeReometry(range));
            }
            Geometry gg = new CombinedGeometry(GeometryCombineMode.Exclude, selectionGeometry, new RectangleGeometry(activeRect));
            drawingContext.DrawGeometry(Background, null, gg);
            if (Selection is CompositeRange)
            {
                drawingContext.DrawRectangle(null, new Pen(Brushes.Black, 1), activeRect);
            }
        }
        RectangleGeometry GetRangeReometry (Range range)
        {
            Rect result = GetRect(range.TopLeftCell.Address, range.ColumnSpan, range.RowSpan);
            if (range.IsFullRow)
                result = new Rect(0, result.Y, ActualWidth, result.Height);
            if (range.IsFullColumn)
                result = new Rect(result.X, 0, result.Width, ActualHeight);
            return new RectangleGeometry(result);
        }

        static IEnumerable<Range> GetSimpleRanges (Range range)
        {
            if (range is CompositeRange)
                foreach (var r in ((CompositeRange)range).Ranges)
                {
                    yield return r;
                }
            yield return range;
        }



        public Brush Background
        {
            get { return (Brush)GetValue(BackgroundProperty); }
            set { SetValue(BackgroundProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Background.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BackgroundProperty =
            DependencyProperty.Register("Background", typeof(Brush), typeof(SelectionAndActiveControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

        
      /*  private readonly Brush brush = CreateBrush();

        private static Brush CreateBrush()
        {
            var result = new SolidColorBrush(Color.FromArgb(0xFF / 4, 0xAB, 0xB3, 0xD7));
            result.Freeze();
            return result;
        }*/

        protected override Size ArrangeOverride(Size finalSize)
        {
            if (Rows != null && Columns != null)
            {
                layoutInfo = new WorksheetGrid.LayoutInfo(new CellPosition { Column = Left, Row = Top }, Columns, Rows,
                                                          finalSize);
            }
            
                
            return base.ArrangeOverride(finalSize);
        }
    }
}
